home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
182_01
/
rb_215.c
< prev
next >
Wrap
Text File
|
1990-07-30
|
18KB
|
817 lines
#define VERSION "2.15 03-04-85"
/*% cc -DUSG -DNFGVMIN -O -K % -o rb
*
* rb.c By Chuck Forsberg
*
* A program for Unix which can receive
* files from computers running YAM or MODEM.
* If no filename is given, YAM batch mode is assumed.
*
* Iff the program is invoked by rbCOMMAND, output is piped to
* "COMMAND filename"
*
* Supports the CRC option or regular checksum.
* Received pathnames containing no lowercase letters will be changed to lower
* case unless -u option is given.
*
* Unless the -b (binary) option is given, \r is discarded and
* ^Z (which is also discarded) acts as end of file.
*
* Any slashes in the pathname are changed to underscore.
* If the raw pathname ends in .MSG or .TXT, any existing file will
* be appended to rather than replaced. Trailing periods are eliminated.
*
* If the raw pathname ends in any of the extensions in Extensions,
* or .?Q* (squeezed file), or if the first sector contains binary-like
* data (parity bits or characters in the range 0 to 6 before ^Z is seen),
* or if the transmitted file mode has the 0100000 but set,
* that file will be received in binary mode anyway.
*
*
* A log of activities is appended to LOGFILE with the -v option
* If stdout and stderr refer to different devices, progress is displayed to
* stderr.
*
* rb is derived from yam2.c and sb.c
* rb uses Unix System III buffered input to reduce CPU time.
* USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
* cc -O -DV7 rb.c -o rb Unix V7, BSD 2.8 - 4.2
* cc -O -DUSG rb.c -o rb USG (3.0) Unix
* cc -o rb.c Regulus
* (Don't try this on Unix, you'll clobber the source!)
* Unix is a trademark of Western Electric Company
*
* Regulus conventions 1-10-83 CAF
*
* Some systems (Venix, Coherent, Regulus) do not support tty raw mode
* read(2) the same way as Unix. ONEREAD must be defined to force one
* character reads for these systems. Added 7-01-84 CAF
*
* Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
*
* NFGVMIN Added 1-13-85 CAF for PC-AT Xenix systems where c_cc[VMIN]
* doesn't seem to work (even though it compiles without error!).
*/
#define LOGFILE "/tmp/rblog"
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <ctype.h>
FILE *popen();
#define OK 0
#define FALSE 0
#define TRUE 1
#define ERROR (-1)
#define HOWMANY 133
#include "rbsb.c" /* most of the system dependent stuff here */
char *substr();
FILE *fout;
char *Extensions[] = {
".A",
".ARC",
".CCC",
".CL",
".CMD",
".COM",
".CRL",
".DAT",
".DIR",
".EXE",
".O",
".OBJ",
".OVL",
".PAG",
".REL",
".SAV",
".SUB",
".SWP",
".SYS",
".TAR",
".UTL",
".a",
".o",
".tar",
""
};
/* Ward Christensen / CP/M parameters - Don't change these! */
#define ENQ 005
#define CAN ('X'&037)
#define XOFF ('s'&037)
#define XON ('q'&037)
#define SOH 1
#define STX 2
#define EOT 4
#define ACK 6
#define NAK 025
#define CPMEOF 032
#define WANTCRC 0103 /* send C not NAK to get crc not checksum */
#define TIMEOUT (-2)
#define ERRORMAX 5
#define RETRYMAX 5
#define WCEOT (-10)
#define SECSIZ 128 /* cp/m's Magic Number record size */
#define PATHLEN 257 /* ready for 4.2 bsd ? */
#define KSIZE 1024 /* record size with k option */
#define UNIXFILE 0x8000 /* happens to the the S_IFREG file mask bit for stat */
int Lastrx;
int Crcflg;
int Firstsec;
int Eofseen; /* indicates cpm eof (^Z) has been received */
int totblocks; /* total number of blocks received */
int errors;
#define DEFBYTL 2000000000L /* default rx file size */
long Bytesleft; /* number of bytes of incoming file left */
long Modtime; /* Unix style mod time for incoming file */
short Filemode; /* Unix style mode for incoming file */
char Pathname[PATHLEN];
char *Progname; /* the name by which we were called */
int Batch=0;
int Wcsmask=0377;
int Topipe=0;
int MakeLCPathname=TRUE; /* make received pathname lower case */
int Verbose=0;
int Quiet=0; /* overrides logic that would otherwise set verbose */
int Rxbinary=FALSE; /* receive all files in bin mode */
int Thisbinary; /* current file is to be received in bin mode */
int Blklen; /* record length of received packets */
char secbuf[KSIZE];
char linbuf[KSIZE];
int Lleft=0; /* number of characters in linbuf */
jmp_buf tohere; /* For the interrupt on RX timeout */
unsigned short updcrc();
alrm()
{
longjmp(tohere, -1);
}
/* called by signal interrupt or terminate to clean things up */
bibi(n)
{
canit(); mode(0);
fprintf(stderr, "sb: caught signal %d; exiting", n);
exit(128+n);
}
main(argc, argv)
char *argv[];
{
register char *cp;
register npats;
char *virgin, **patts;
int exitcode;
setbuf(stderr, NULL);
chkinvok(virgin=argv[0]); /* if called as [-]rbCOMMAND set flag */
npats = 0;
while (--argc) {
cp = *++argv;
if (*cp == '-') {
while( *++cp) {
switch(*cp) {
case '1':
iofd = 1; break;
case '7':
Wcsmask = 0177;
case 'b':
Rxbinary=TRUE; break;
case 'k':
case 'c':
Crcflg=TRUE; break;
case 'q':
Quiet=TRUE; Verbose=0; break;
case 'u':
MakeLCPathname=FALSE; break;
case 'v':
++Verbose; break;
default:
usage();
}
}
}
else if ( !npats && argc>0) {
if (argv[0][0]) {
npats=argc;
patts=argv;
}
}
}
if (npats > 1)
usage();
if (Verbose) {
if (freopen(LOGFILE, "a", stderr)==NULL) {
printf("Can't open log file %s\n",LOGFILE);
exit(0200);
}
setbuf(stderr, NULL);
fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
}
if (fromcu() && !Quiet) {
if (Verbose == 0)
Verbose = 2;
}
mode(1);
if (signal(SIGINT, bibi) == SIG_IGN) {
signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
}
else {
signal(SIGINT, bibi); signal(SIGKILL, bibi);
}
if (wcreceive(npats, patts)==ERROR) {
exitcode=0200;
canit();
}
mode(0);
if (exitcode != 0) /* bellow again with all thy might. */
canit();
#ifdef REGULUS
else
printf("\6\6\6\6\6\n"); /* Regulus doesn't wait ... */
#endif
exit(exitcode);
}
usage()
{
fprintf(stderr,"%s %s by Chuck Forsberg\n", Progname, VERSION);
fprintf(stderr,"Usage: rb [-17buv]\n\tor rb [-1bcuv] file\n");
exit(1);
}
wcreceive(argc, argp)
char **argp;
{
if (Batch || argc==0) {
Crcflg=(Wcsmask==0377);
fprintf(stderr, "rb: ready ");
for (;;) {
totblocks=0;
if (wcrxpn(secbuf)== ERROR)
goto fubar;
if (secbuf[0]==0)
return OK;
if (procheader(secbuf) == ERROR)
goto fubar;
if (wcrx()==ERROR)
goto fubar;
}
} else {
totblocks=0; Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
strcpy(Pathname, *argp);
if (fopen(*argp, "r") != NULL) {
fprintf(stderr, "rb: %s exists\n", Pathname);
goto fubar;
}
fprintf(stderr, "\nrb: ready to receive %s ", Pathname);
if ((fout=fopen(Pathname, "w")) == NULL)
return ERROR;
if (wcrx()==ERROR)
goto fubar;
}
return OK;
fubar:
canit();
if (Topipe && fout) {
pclose(fout); return ERROR;
}
if (fout)
fclose(fout);
return ERROR;
}
/*
* Fetch a pathname from the other end as a C ctyle ASCIZ string.
* Length is indeterminate as long as less than Blklen
* a null string represents no more files
*/
wcrxpn(rpn)
char *rpn; /* receive a pathname */
{
register c;
#ifdef NFGVMIN
readline(1);
#else
purgeline();
#endif
et_tu:
Firstsec=TRUE;
sendline(Crcflg?WANTCRC:NAK);
while ((c = wcgetsec(rpn, 100)) != 0) {
log( "Pathname fetch returned %d\n", c);
if (c == WCEOT) {
sendline(ACK); readline(1); goto et_tu;
}
return ERROR;
}
sendline(ACK);
return OK;
}
/*
* Adapted from CMODEM13.C, written by
* Jack M. Wierda and Roderick W. Hart
*/
wcrx()
{
register int sectnum, sectcurr;
register char sendchar;
register char *p;
int cblklen; /* bytes to dump this block */
time_t timep[2];
Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
sendchar=Crcflg?WANTCRC:NAK;
for (;;) {
sendl